#region Using Directives
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.IO;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.Web.Services2;
using Microsoft.Web.Services2.Messaging;
using Microsoft.Web.Services2.Addressing;
using CSF.Communications.Sdp.ServiceLogic.Entities;
using System.Xml;
using Microsoft.Web.Services2.Security;
using Microsoft.Web.Services2.Security.Tokens;
using CSF.Communications.Sdp.ServiceLogic.Utilities;
using System.Xml.XPath;
using System.Xml.Xsl;
using CSF.Communications.Sdp.ServiceLogic.Exceptions;
using Microsoft.ApplicationBlocks.ExceptionManagement;
using CSF.Communications.Sdp.ServiceLogic.WFUtility;
#endregion


namespace CSF.Communications.Sdp.ServiceLogic.Interface
{
    /// <summary>
    /// Summary description for Process
    /// </summary>
    public class Process
    {

        #region Members
        private DataServiceProvider _dsp;
        private MapServiceProvider _msp;
        private RulePolicyProvider _rsp;
        private DataTransferProvider _dtp;
        private MessageFactory _objMessageFactory;
        private SoapUtility _objSoapUtility;
        #endregion

        #region Constructor
        /// <summary>
        /// 
        /// </summary>
        public Process()
        {

            _dsp = new CSF.Communications.Sdp.ServiceLogic.Utilities.DataServiceProvider();
            _msp = new MapServiceProvider();
            _rsp = new RulePolicyProvider();
            _dtp = new DataTransferProvider();
            _objMessageFactory = new MessageFactory();
            _objSoapUtility = new SoapUtility();

        }
        #endregion

        #region GetMidFromDB
        /// <summary>
        /// 
        /// </summary>
        public CSF_MID GetMidFromDB(SoapRequestState request)
        {
           CSF_MID mid=null;
           try
           {

               mid = _dsp.GetMidFromDB(request);

           }
           catch (Exception ex)
           {
               throw new SDPDataException(Convert.ToInt64(SDPDataError.ErrorFetchingMid),ex.Message);
           }
           return mid;

        }
        #endregion

        #region UpdateServiceLogicState
        /// <summary>
        /// 
        /// </summary>
        public void UpdateServiceLogicState(SoapRequestState request,ServiceLogicStateEnum state)
        {

            try
            {
            
                _dsp.UpdateServiceLogicState( request, state);

            }
            catch (Exception ex)
            {
                throw new SDPDataException(Convert.ToInt64(SDPDataError.ErrorUpdatingServicelogicStatus),ex.Message);
            }
                   

        }
        #endregion

        #region GetMidAfterVASResponse
        /// <summary>
        /// 
        /// </summary>
        /// <param name="env"></param>
        /// <param name="mid_old"></param>
        /// <returns></returns>
        public CSF_MID GetMidAfterVASResponse(SoapEnvelope env, CSF_MID mid_old)
        {

            CSF_MID mid_new = null;
            ModifyStateResponse msresponse = null;
            try
            {

                ServiceLogicReceiveActions responseAction = (ServiceLogicReceiveActions)Enum.Parse(typeof(ServiceLogicReceiveActions), env.Body.FirstChild.Name, true);
                string resultCode = null;
                string vasAction = null;
                string serviceID = null;

                switch (responseAction)
                {
                    case ServiceLogicReceiveActions.IsUserInRoleResponse:
                        IsUserInRoleResponse response = new IsUserInRoleResponse();
                        response = IsUserInRoleResponse.DeSerializeObject(env.Body.InnerXml);
                        resultCode = response.ResultCode;
                        vasAction = ParticipantActions.CheckUserInRole.ToString();
                        serviceID = ParticipantVASID.CSF_PM_RoleManager.ToString();
                        break;

                    case ServiceLogicReceiveActions.ModifyStateResponse:
                        msresponse = new ModifyStateResponse();
                        msresponse = ModifyStateResponse.DeSerializeObject(env.Body.InnerXml);
                        resultCode = msresponse.ResultCode;
                        vasAction = ParticipantActions.ModifyState.ToString();
                        serviceID = msresponse.Target.ToString();
                        break;

                    case ServiceLogicReceiveActions.UserServiceMappingAddResponse:

                        UserServiceMappingAddResponse usmresponse = new UserServiceMappingAddResponse();
                        usmresponse = UserServiceMappingAddResponse.DeSerializeObject(env.Body.InnerXml);
                        resultCode = usmresponse.ResultCode;
                        vasAction = ParticipantActions.CreateMapping.ToString();
                        serviceID = ParticipantVASID.CSF_PM_UserServiceMapping.ToString();
                        break;
                    case ServiceLogicReceiveActions.UserMapManagerCreateMapResponse:

                        UserMapManagerCreateMapResponse mapresponse = new UserMapManagerCreateMapResponse();
                        mapresponse = UserMapManagerCreateMapResponse.DeSerializeObject(env.Body.InnerXml);
                        resultCode = mapresponse.ResultCode;
                        vasAction = ParticipantActions.CreateMap.ToString();
                        serviceID = ParticipantVASID.CSF_IdM_UserMapManager.ToString();
                        break;
                    default:
                        break;  // throw some error..

                }

                mid_old.RoutingData.CurrentResultCode = resultCode;

                mid_old.RoutingData.CurrentState = mid_old.RoutingData.NextStates;

                if (mid_old.RoutingData.CalledStates == String.Empty)
                {
                    mid_old.RoutingData.CalledStates = mid_old.RoutingData.NextStates;
                }
                else
                {
                    mid_old.RoutingData.CalledStates = mid_old.RoutingData.CalledStates + " " + mid_old.RoutingData.NextStates;
                }


                int vasCount=0;
                foreach (ServiceLogicPayloadTypeVASData vasdata in mid_old.VASDataCollection)
                {
                    if (vasdata.VASID.Equals(serviceID))
                    {
                        if (msresponse != null && msresponse.Parameters != null && msresponse.Parameters.Any != null && msresponse.Parameters.Any.Length>0)
                        {
                           try
                            {
                                mid_old.VASDataCollection[vasCount].VasResponse = new ServiceLogicPayloadTypeVASDataVasResponse[1];
                                mid_old.VASDataCollection[vasCount].VasResponse[0] = new ServiceLogicPayloadTypeVASDataVasResponse();
                                mid_old.VASDataCollection[vasCount].VasResponse[0].ResultCode = resultCode;
                                mid_old.VASDataCollection[vasCount].VasResponse[0].Parameters = new ParametersType();
                                mid_old.VASDataCollection[vasCount].VasResponse[0].Parameters.Any = msresponse.Parameters.Any;
                            }
                            catch(Exception ex)
                            {
                                ExceptionManager.Publish(ex);
                            }
                        }
                    }
                    vasCount++;
                }

                mid_new = mid_old;
                               
            }
            catch (Exception ex)
            {
                throw new SDPSystemException(Convert.ToInt64(SDPSystemError.SDPConstructMidfromVASResponseException), ex.Message);
            }
            return mid_new;
        }
        #endregion

        //#region ExecutePolicy
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="mid"></param>
        ///// <returns></returns>
        //public CSF_MID ExecutePolicy(CSF_MID mid, string policyName, int majorVersion, int minorVersion)
        //{

        //    RulePolicyProvider rulesProvider = new RulePolicyProvider();
        //    try
        //    {

        //        return rulesProvider.ExecutePolicy(mid, policyName, majorVersion, minorVersion);

        //    }
        //    catch (Exception ex)
        //    {
        //        throw new SDPSystemException(Convert.ToInt64(SDPSystemError.SDPPolicyExecutionException), ex.Message);
        //    }

        //}

        //#endregion

        #region ExecutePolicy
        /// <summary>
        /// 
        /// </summary>
        /// <param name="mid"></param>
        /// <returns></returns>
        public CSF_MID ExecutePolicy(CSF_MID mid, string policyName, int majorVersion, int minorVersion)
        {


           // string policyName = "ServiceLogicRules";
            RulesUtility rulesProvider = new RulesUtility(mid,policyName);

            try
            {

                return rulesProvider.ExecutePolicy(mid, policyName, majorVersion, minorVersion);

            }
            catch (Exception ex)
            {
                throw new SDPSystemException(Convert.ToInt64(SDPSystemError.SDPPolicyExecutionException), ex.Message);
            }

        }

        #endregion

        #region GetMid
        /// <summary>
        /// 
        /// </summary>
        /// <param name="payload"></param>
        /// <returns></returns>
        public CSF_MID GetMid(ServiceLogicPayloadType payload)
        {
            CSF_MID mid;

            try
            {
                mid = DataTransferProvider.PayloadtoMid(payload);
            }
            catch (Exception ex)
            {
                throw new SDPSystemException(Convert.ToInt64(SDPSystemError.SDPMidToPayloadException), ex.Message);
            }
            
            return mid;

        }
        #endregion

        #region GetPolicyFromDB
        /// <summary>
        /// 
        /// </summary>
        /// <param name="mid"></param>
        /// <returns></returns>
        public string GetPolicyFromDB(CSF_MID mid)
        {
            try
            {
                return _dsp.GetPolicyFromDB(mid);
            }
            catch (Exception ex)
            {
                throw new SDPDataException(Convert.ToInt64(SDPDataError.ErrorQueryingSBERulesPolicyTableInDB), ex.Message);
            }

        }
        #endregion

        #region PersistState
        /// <summary>
        /// 
        /// </summary>
        /// <param name="requestEnv"></param>
        /// <returns></returns>
        public SoapRequestState PersistState(SoapEnvelope requestEnv)
        {
            SoapRequestState request = new SoapRequestState();
            try
            {
                request.FromAddress = requestEnv.Context.Addressing.From.Address.Value;
                request.ToAddress = requestEnv.Context.Addressing.To.Value;
                XmlNodeList nl = requestEnv.Header.GetElementsByTagName("csfse:SessionID");
                request.SessionID = nl[0].InnerText;
                 XmlDocument doc= new XmlDocument();
                  
                //nl = requestEnv.Header.GetElementsByTagName("WESRequestUUID");
                nl = requestEnv.Context.Addressing.From.ReferenceProperties.GetXml(doc).GetElementsByTagName("RequestUUID");
                //request.RequestUUID = nl[0].InnerText;
                
                if (nl.Count > 0)
                {
                    request.RequestUUID = nl[0].InnerXml;

                }
                else
                {
                    nl = requestEnv.GetElementsByTagName("RequestUUID");
                    if (nl.Count > 0)
                    {
                        request.RequestUUID = nl[0].InnerXml;

                    }
                }

                nl = requestEnv.Header.GetElementsByTagName("csfse:OriginalFaultTo");
                if (nl.Count > 0)
                {

                    request.ReplytoUri = new Uri(nl[0].InnerText);
                }

               // request.SessionID = "urn:196adba2-14a3-49f2-b10d-fece2b5c77c4";
               //request.RequestUUID = "23F3182E-9E18-47AF-B5A8-8243E918232D";


            }
            catch (Exception ex)
            {
                throw new SDPWSEException(Convert.ToInt64(SDPWSEError.PersistingStateException), ex.Message);
            }
           
            return request;
        }
        #endregion

        #region ProcessNextParticipant
        /// <summary>
        /// 
        /// </summary>
        /// <param name="mid"></param>
        /// <param name="vasrequest"></param>
        /// <returns></returns>
        public void ProcessNextParticipant(CSF_MID mid,SoapRequestState requeststate,bool isVasResponse, out VasRequestInternal vasrequest)
        {
            string vasID;
            string action;
            VasRequestInternal vasrequestinternal=new VasRequestInternal();
            XmlDocument requestXml;
            try
            {
                if (mid.RoutingData != null)
                {
                    if (mid.RoutingData.NextStates.ToUpper() != "END")
                    {
                        if (mid.RoutingData.NextStates != null)
                        {
                            string[] nextstate = mid.RoutingData.NextStates.Split('.');
                            vasID = nextstate[0];
                            action = nextstate[1];
                            if (mid.RoutingData.IsSSORequired && mid.RoutingData.SsoApplicationName!=null)
                            {
                                mid = _objMessageFactory.ConstructDynamicMID(mid, "IsSSORequired");
                                

                            }
                            if (mid.RoutingData.IsUSMRequired&& mid.RoutingData.UsmServiceId!=null)
                            {
                                mid = _objMessageFactory.ConstructDynamicMID(mid, "IsUSMRequired");
                            }
                            

                            if (mid.RoutingData.Maps != null && mid.RoutingData.Maps != String.Empty)
                            {
                                try
                                {

                                    mid = _objMessageFactory.ConstructDynamicMID(mid);

                                    mid.RoutingData.Maps = String.Empty;

                                 }
                                catch(Exception ex)
                                {
                                    ExceptionManager.Publish(ex);
                                }
                            }
                           
                            vasrequestinternal = _objMessageFactory.ConstructVASInternalrequest(mid, vasID, action);
                            if (vasrequestinternal != null)
                            {
                                requestXml = _objMessageFactory.PrepareRequestToVas(vasrequestinternal, vasID, vasrequestinternal.Action);
                                _objSoapUtility.SendRequest(requeststate, requestXml, vasrequestinternal.Action);
                                
                                _dsp.InsertMidinDB(requeststate, null, mid, null, isVasResponse);
                            }
                            else
                            {
                                throw new Exception("Error Constructing VAS Internal Request");
                            }
                        }
                    }
                    else
                    {
                        
                        //Call Service Logic Completion Status
                        serviceLogicResponse(requeststate, ServiceLogicStateEnum.Completed, mid,""); 
                        //_dsp.ArchiveMid(requeststate, mid);
                        //_dsp.UpdateServiceLogicState(requeststate, ServiceLogicStateEnum.Completed);
                        //_dsp.DeleteMidFromDB(requeststate);
                        ServiceLogicCompletionStatus response = _objMessageFactory.GetServiceLogicCompletion(mid,"");
                        //_objSoapUtility.SendServicelogicResponse(requeststate, response);
                    }
                }
            }
            
            catch (Exception ex)
            {
                ExceptionManager.Publish(ex, Convert.ToInt32(SDPSystemError.SDPSystemException));
                //Call Service Logic Completion Status
                serviceLogicResponse(requeststate, ServiceLogicStateEnum.TimedOut, mid ,ex.Message.ToString());    
            }
            
            vasrequest = vasrequestinternal;
            
            
        }

        public void serviceLogicResponse(SoapRequestState requeststate,ServiceLogicStateEnum status,CSF_MID mid,string errorMessage )
        {
            try
            {

                _dsp.ArchiveMid(requeststate, mid);
                _dsp.UpdateServiceLogicState(requeststate,status);
                _dsp.DeleteMidFromDB(requeststate);
                ServiceLogicCompletionStatus response = _objMessageFactory.GetServiceLogicCompletion(mid,mid.RoutingData.ErrorMessageToSbe);
                _objSoapUtility.SendServicelogicResponse(requeststate, response);


            }
            catch(Exception ex)
            {
                ExceptionManager.Publish(ex, Convert.ToInt32(SDPSystemError.SDPSystemException));
            }
        
        }
        #endregion
       
    }
}